
package com.mdc.mansion.web.modules.system.service;

import java.util.Date;
import java.util.List;

import com.mdc.mansion.component.cache.common.util.LocalCacheUtils;
import com.mdc.mansion.common.util.Encodes;
import com.mdc.mansion.common.util.StringUtils;
import com.mdc.mansion.common.util.WebUtil;
import com.mdc.mansion.dataaccess.common.persistence.Page;
import com.mdc.mansion.dataaccess.modules.system.dao.DictDao;
import com.mdc.mansion.dataaccess.modules.system.dao.MenuDao;
import com.mdc.mansion.dataaccess.modules.system.dao.RoleDao;
import com.mdc.mansion.dataaccess.modules.system.dao.UserDao;
import com.mdc.mansion.dataaccess.modules.system.entity.Dict;
import com.mdc.mansion.dataaccess.modules.system.entity.Menu;
import com.mdc.mansion.dataaccess.modules.system.entity.Role;
import com.mdc.mansion.dataaccess.modules.system.entity.User;
import com.mdc.mansion.web.common.security.Digests;
import com.mdc.mansion.web.modules.system.security.SystemAuthorizingRealm;
import com.mdc.mansion.web.modules.system.utils.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.mdc.mansion.web.modules.system.utils.DictUtils;

/**
 * 系统管理，安全相关实体的管理类,包括用户、角色、菜单.
 * @author ThinkGem
 * @version 2013-5-15
 */
@Service
@Transactional(readOnly = true)
public class SystemService  {
	
	public static final String HASH_ALGORITHM = "SHA-1";
	public static final int HASH_INTERATIONS = 1024;
	public static final int SALT_SIZE = 8;
	
	@Autowired
	private UserDao userDao;
	@Autowired
	private RoleDao roleDao;
	@Autowired
	private MenuDao menuDao;
	@Autowired
	private DictDao dictDao;
	@Autowired
	private SystemAuthorizingRealm systemRealm;
	
	
	//-- User Service --//
	
	public User getUser(String id) {
		User user = userDao.get(id);
		if(user!=null){
			if(user.isAdmin()){
				user.setRoleList(roleDao.findAllList(new Role()));
			}else{
				user.setRoleList(roleDao.findList(new Role(user)));
			}
		}
		return user;
	}
	
	public Page<User> findUser(User user) {
		Page<User> page=new Page<User>();
		page.setList(userDao.findList(user));
		return page;
	}

	
	public User getUserByLoginName(String loginName) {
		User user=new User(loginName);
		return userDao.getByLoginName(user);
	}

	@Transactional(readOnly = false)
	public void saveUser(User user) {
		User u= UserUtils.getUser();
		user.setUpdateBy(u);
		if (StringUtils.isBlank(user.getId())){
			user.preInsert();
			user.setCreateBy(u);
			userDao.insert(user);
		}else{
			user.preUpdate();
			userDao.update(user);
		}
		userDao.deleteUserRole(user);
		userDao.insertUserRole(user);
		systemRealm.clearAllCachedAuthorizationInfo();
		
	}

	@Transactional(readOnly = false)
	public void deleteUser(User user) {
		userDao.delete(user);
	}
	
	@Transactional(readOnly = false)
	public void updatePasswordById(String id, String loginName, String newPassword) {
		User user = new User(id);
		user.setPassword(entryptPassword(newPassword));
		userDao.updatePasswordById(user);
		systemRealm.clearCachedAuthorizationInfo(loginName);
	}
	
	@Transactional(readOnly = false)
	public void updateUserLoginInfo(User user) {
		user.setOldLoginIp(user.getLoginIp());
		user.setOldLoginDate(user.getLoginDate());
		// 更新本次登录信息
		user.setLoginIp(WebUtil.getRemoteIp());
		user.setLoginDate(new Date());
		userDao.updateLoginInfo(user);
	}
	
	/**
	 * 生成安全的密码，生成随机的16位salt并经过1024次 sha-1 hash
	 */
	public static String entryptPassword(String plainPassword) {
		byte[] salt = Digests.generateSalt(SALT_SIZE);
		byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS);
		return Encodes.encodeHex(salt)+Encodes.encodeHex(hashPassword);
	}
	
	/**
	 * 验证密码
	 * @param plainPassword 明文密码
	 * @param password 密文密码
	 * @return 验证成功返回true
	 */
	public static boolean validatePassword(String plainPassword, String password) {
		byte[] salt = Encodes.decodeHex(password.substring(0,16));
		byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS);
		return password.equals(Encodes.encodeHex(salt)+Encodes.encodeHex(hashPassword));
	}
	
	//-- Role Service --//
	
	public Role getRole(String id) {
		return roleDao.get(id);
	}

	public Role findRoleByName(String name) {
		Role role = new Role();
		role.setName(name);
		return roleDao.getByName(role);
	}
	
	public List<Role> findAllRole(){
		return roleDao.findAllList(new Role());
	}
	
	@Transactional(readOnly = false)
	public void saveRole(Role role) {
		User u=UserUtils.getUser();
		role.setUpdateBy(u);
		if (StringUtils.isBlank(role.getId())){
			role.setCreateBy(u);
			role.preInsert();
			roleDao.insert(role);
		}else{
			role.preUpdate();
			roleDao.update(role);
		}
		
		// 更新角色与菜单关联
		roleDao.deleteRoleMenu(role);
		if (role.getMenuList().size() > 0){
			roleDao.insertRoleMenu(role);
		}
		
		systemRealm.clearAllCachedAuthorizationInfo();
		UserUtils.removeCache(UserUtils.CACHE_ROLE_LIST);
	}

	@Transactional(readOnly = false)
	public void deleteRole(Role role) {
		roleDao.delete(role);
		systemRealm.clearAllCachedAuthorizationInfo();
		UserUtils.removeCache(UserUtils.CACHE_ROLE_LIST);
		
	}
	
	@Transactional(readOnly = false)
	public Boolean outUserInRole(Role role, String userId) {
		User user = userDao.get(userId);
		List<String> roleIds = user.getRoleIdList();
		List<Role> roles = user.getRoleList();
		// 
		if (roleIds.contains(role.getId())) {
			roles.remove(role);
			saveUser(user);
			return true;
		}
		return false;
	}
	
	@Transactional(readOnly = false)
	public User assignUserToRole(Role role, String userId) {
		User user = userDao.get(userId);
		List<String> roleIds = user.getRoleIdList();
		if (roleIds.contains(role.getId())) {
			return null;
		}
		user.getRoleList().add(role);
		saveUser(user);		
		return user;
	}

	//-- Menu Service --//
	
	public Menu getMenu(String id) {
		return menuDao.get(id);
	}

	public List<Menu> findAllMenu(){
		return UserUtils.getMenuList();
	}
	
	@Transactional(readOnly = false)
	public void updateMenuSort(Menu menu) {
		menuDao.updateSort(menu);
		// 清除用户菜单缓存
		UserUtils.removeCache(UserUtils.CACHE_MENU_LIST);
	}

	
	@Transactional(readOnly = false)
	public void saveMenu(Menu menu) {

		// 获取父节点实体
		menu.setParent(this.getMenu(menu.getParent().getId()));
		
		// 获取修改前的parentIds，用于更新子节点的parentIds
		String oldParentIds = menu.getParentIds(); 
		
		// 设置新的父节点串
		menu.setParentIds(menu.getParent().getParentIds()+menu.getParent().getId()+",");
		menu.setUpdateBy(UserUtils.getUser());
		// 保存或更新实体
		if (StringUtils.isBlank(menu.getId())){
			menu.setCreateBy(UserUtils.getUser());
			menu.preInsert();
			menuDao.insert(menu);
		}else{
			menu.preUpdate();
			menuDao.update(menu);
		}
		
		// 更新子节点 parentIds
		Menu m = new Menu();
		m.setParentIds("%,"+menu.getId()+",%");
		List<Menu> list = menuDao.findByParentIdsLike(m);
		for (Menu e : list){
			e.setParentIds(e.getParentIds().replace(oldParentIds, menu.getParentIds()));
			menuDao.updateParentIds(e);
		}
		// 清除用户菜单缓存
		UserUtils.removeCache(UserUtils.CACHE_MENU_LIST);
		// 清除权限缓存
		systemRealm.clearAllCachedAuthorizationInfo();
		// 清除日志相关缓存
		
	}

	@Transactional(readOnly = false)
	public void deleteMenu(Menu menu) {
		menuDao.delete(menu);
		systemRealm.clearAllCachedAuthorizationInfo();
		UserUtils.removeCache(UserUtils.CACHE_MENU_LIST);
	}	
	
	
	public Dict getDict(String id){
		return dictDao.get(id);
	}
	
	@Transactional(readOnly = false)
	public void saveDict(Dict dict){
		User user=UserUtils.getUser();
		dict.setUpdateBy(user);
		if(StringUtils.isBlank(dict.getId())){
			dict.preInsert();
			dict.setCreateBy(user);
			dictDao.insert(dict);
		}else{
			dictDao.update(dict);
		}
		LocalCacheUtils.remove(DictUtils.CACHE_DICT_MAP);
	}
	
	@Transactional(readOnly = false)
	public void deleteDict(Dict dict){
		dictDao.delete(dict);
		LocalCacheUtils.remove(DictUtils.CACHE_DICT_MAP);
		
	}
}
